package com.jinghang.hos.mybatis;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Set;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;

/**
 * @Configuration
 *  指示类声明一个或多个{@link Bean @Bean}方法，并可由Spring容器处理，
 *  以便在运行时为这些Bean生成Bean定义和服务请求
 * @MapperScan
 *  在使用Java配置时，使用这个注释注册MyBatis映射器接口。
 *  其实就是dao层接口
 *
 */
@Configuration
@MapperScan(basePackages = HosDataSourceConfig.PACKAGE,
        sqlSessionFactoryRef = "HosSqlSessionFactory")
public class HosDataSourceConfig {

  static final String PACKAGE = "com.jinghang.hos.**";

  /**
   * @Bean spring Bean 功能上等同于java Bean 就是java 对象
   *        通过@Bean声明为spring Bean，可以被spring ioc 容器管理（创建，删除）该对象
   *@Primary
   *    指示当多个候选项符合自动连接单值依赖项的条件时，应优先考虑bean。
   *    如果在候选bean中只存在一个“primary”bean，那么它就是autowired值。
   *    https://www.jianshu.com/p/b0644c13a964
   *      一个接口有多个实现，默认使用加上@Primary的实现
   * @return DataSource DataSource
   * @throws IOException IOException
   */
  @Bean(name = "HosDataSource")
  @Primary
  public DataSource hosDataSource() throws IOException {

    //1.获取properties配置文件配置信息
    ResourceLoader loader = new DefaultResourceLoader();
    InputStream inputStream = loader.getResource("classpath:application.properties")
            .getInputStream();
    Properties properties = new Properties();
    properties.load(inputStream);
    Set<Object> keys = properties.keySet();

    //2.根据前缀巧妙处理配置信息
    Properties dsproperties = new Properties();
    for (Object key : keys) {
      if (key.toString().startsWith("datasource")) {
        dsproperties.put(key.toString().replace("datasource.", ""), properties.get(key));
      }
    }

    //通过 HikariDataSourceFactory 生成datasource
    HikariDataSourceFactory factory = new HikariDataSourceFactory();
    factory.setProperties(dsproperties);
    //try
    inputStream.close();
    return factory.getDataSource();

  }

  /**
   *
   * @param phoenixDataSource
   * @return
   * @throws Exception
   *
   * @Qualifier 使用到时自动注入 HosDataSource 对象 可以打断点测试
   */
  @Bean(name = "HosSqlSessionFactory")
  @Primary
  public SqlSessionFactory hosSqlSessionFactory(
          @Qualifier("HosDataSource") DataSource phoenixDataSource) throws Exception {

    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(phoenixDataSource);

    //读取配置（resource文件加下文件）
    ResourceLoader loader = new DefaultResourceLoader();
    String resource = "classpath:mybatis-config.xml";
    factoryBean.setConfigLocation(loader.getResource(resource));

    //获取sqlSessionFactory实例
    factoryBean.setSqlSessionFactoryBuilder(new SqlSessionFactoryBuilder());

    //try
    return factoryBean.getObject();
  }
}

